#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <error.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>

#define CONFIG_NUM 5
typedef enum profile_member_pos
{
	PF_NAME = 0,
	PF_TOKEN,
	PF_FIXED,
	PF_VSTOKEN,
	PF_ASTOKEN,
	PF_VETOKEN,
	PF_AETOKEN,
	PF_VATOKEN,
	PF_PTZTOKEN,
	PF_MDTOKEN,
	PF_AOTOKEN,
	PF_ADTOKEN,

	PF_MAX_POS
}PROFILE_MEM_POS;

static int profile_num = 2;
static char *profiles[CONFIG_NUM][12] = {
	{
		"NetransProfile",//name
		"NetransProfile",//token
		"false",//fixed
		"vsource_1",//video source token
		"asource_1",//audio source token
		"vencoder_1",//video encoder token
		"aencoder_1",//audio encoder token
		"vanalytics_1",//video analytics token
		"ptz_1",//ptz token
		"meta_1",//metadata token
		//extension: audio output, audio decoder
		NULL,
		NULL
	},
	{
		"RecordProfile",
		"RecordProfile",
		"false",
		"vsource_1",
		"asource_1",
		"vencoder_2",
		"aencoder_1",
		"vanalytics_1",
		"ptz_1",
		"meta_1",

		NULL,
		NULL
	}
};

typedef enum VEncoder_Config_Pos
{
	VE_PCMPNUM = 0,
	VE_PCMPLIST,

	VE_NAME,
	VE_USECOUNT,
	VE_TOKEN,
	VE_ENCODE,
	VE_RESOL,
	VE_QUALITY,
	VE_RATE,
	VE_MPEG4,
	VE_H264,
	VE_MULTICAST,
	VE_SESSTIME,
	VE_ANYSIZE,
	VE_ANY,
	VE_ANYATTR,

	VE_MAX_POS
}VE_CONFIG_POS;
static const int ve_config_num = 2;
static char *ve_configurations[CONFIG_NUM][16] = {
	{
		"1",//the number of compatible profile
		"NetransProfile;",//compatible profile list

		"vencoder_1",//name
		"1",//usercount,read-only
		"vencoder_1",//token
		"1",//encodeing, JPEG=0,MPEG4=1,H264=2
		"1280;720;",//resolution:width;height;
		"7",//quality, 1-10
		"25;1;2048;",//video rate control
		"15;0;",//mpeg4 configuration: govlength;profile:sp=0,asp=1
		NULL, //h264 configuration
		"ipv4,0.0.0.0;554;60;true;0;",//multicast configuration: ip;port;ttl;autostart;__size;__any;
		"720000",//session timeout,unit:ms --> PT12M
		"0",//__size
		NULL, //__any
		NULL, //__anyAttribute
	},
	{
		"1",//the number of compatible profile
		"RecordProfile;",//compatible profile list

		"vencoder_2",//name
		"1",//usercount,read-only
		"vencoder_2",//token
		"2",//encodeing, JPEG=0,MPEG4=1,H264=2
		"1280;720;",//resolution
		"7",//quality, 1-10
		"25;1;1024;",//video rate control
		NULL,//mpeg4 configuration: govlength;profile:sp=0,asp=1
		"10;0;", //h264 configuration:govlength;profile:baseline=0,main=1,extended=2,high=3
		"ipv4,0.0.0.0;554;60;true;0;",//multicast configuration: ip;port;ttl;autostart;__size;__any;
		"720000",//session timeout
		"0",//__size
		NULL, //__any
		NULL, //__anyAttribute
	}
};

/*
 * video source configuration
 */
typedef enum VSource_Config_Pos
{
	VS_PCMPNUM = 0,
	VS_PCMPLIST,

	VS_NAME,
	VS_USECOUNT,
	VS_TOKEN,
	VS_SRCTOKEN,
	VS_BOUNDS,
	VS_ANYSIZE,
	VS_ANY,
	VS_ANYATTR,

	VS_MAX_POS
}VS_CONFIG_POS;
static const int vs_config_num = 1;
static const char *vs_configurations[CONFIG_NUM][10] = 
{
	{
		"2",//the number of compatible media profile : 0 -- all compatible
		"NetransProfile;RecordProfile;", //compatible media profile list

		"vsource_1",//name
		"2",//usecount
		"vsource_1",//token
		"vsource_1",//source token
		"1;1;1280;720;",//Bounds: x;y;width;hieght;		
		"0", //__size
		NULL,
		NULL
	}
};

//video output
typedef enum 
{
	VO_NAME = 0,
	VO_USECOUNT,
	VO_TOKEN,
	VO_OPTOKEN,
	VO_ANYSIZE,
	VO_ANY,
	VO_ANYATTR,

	VO_MAX_POS
}VO_CONFIG_POS;
static int vo_config_num = 1;
static char *vo_configurations[CONFIG_NUM][7] = 
{
	{
		"voutput_1", //name
		"1",//usecount
		"voutput_1",//token
		"voutput_1",//output token <physical device>
		"0", //__size
		NULL,
		NULL
	}
};

//audio source
typedef enum ASource_Config_Pos
{
	AS_PCMPNUM = 0,
	AS_PCMPLIST,

	AS_NAME,
	AS_USECOUNT,
	AS_TOKEN,
	AS_SRCTOKEN,
	AS_ANYSIZE,
	AS_ANY,
	AS_ANYATTR,

	AS_MAX_POS
}AS_CONFIG_POS;
static const int as_config_num = 1;
static const char *as_configurations[CONFIG_NUM][9] = 
{
	{
		"0",//the number of compatible profile :0 -- all compatible
		"*",//the compatible profile list

		"asource_1",//name
		"1",//usecount
		"asource_1",//token
		"asource_1",//source token
		"0", //__size
		NULL,
		NULL
	}
};

//audio ouput
typedef enum 
{
	AO_PCMPNUM = 0,
	AO_PCMPLIST,

	AO_NAME,
	AO_USECOUNT,
	AO_TOKEN,
	AO_OPTOKEN,
	AO_SNDPRI,
	AO_OPLEVL,
	AO_ANYSIZE,
	AO_ANY,
	AO_ANYATTR,

	AO_MAX_POS
}AO_CONFIG_POS;
static const int ao_config_num = 1;
static const char *ao_configurations[CONFIG_NUM][11] = 
{
	{
		"0",//the number of compatible profile: 0 -- all compatible
		"*",//the compatible profile list

		"aoutput_1", //name
		"1",//usecount
		"aoutput_1",//token
		"aoutput_1",//output token <physical device>
		"www.onvif.org/ver20/HalfDuplex/Auto",//SendPrimacy:direction
		"80",//OutputLevel: volume setting
		"0", //__size
		NULL,
		NULL
	}
};

/*
 * audio encoder configurations
 */
typedef enum AEncoder_Config_Pos
{
	AE_PCMPNUM = 0,
	AE_PCMPLIST,

	AE_NAME,
	AE_USECOUNT,
	AE_TOKEN,
	AE_ENCODE,
	AE_BITRATE,
	AE_SAMRATE,
	AE_MULTICAST,
	AE_SESSTIME,
	AE_ANYSIZE,
	AE_ANY,
	AE_ANYATTR,

	AE_MAX_POS
}AE_CONFIG_POS;
static const int ae_config_num = 1;
static char *ae_configurations[CONFIG_NUM][13] = 
{
	{
		"0",//the number of compatible profile: 0 -- all compatible
		"*",//compatible profile list

		"aencoder_1",//name
		"2",//usecount
		"aencoder_1",//token
		"0",//audio encoding:G711 - 0,G726 - 1,AAc - 3
		"32",//bitrate,unit:kbps
		"80",//samplerate,unit:kHz
		"ipv4,0.0.0.0;554;60;true;0;",//multicast configuration: ip;port;ttl;autostart;__size;__any;
		"720000",//session timeout,unit:ms --> PT12M
		"0",//__size
		NULL, //__any
		NULL, //__anyAttribute
	}
};

/*
 * audio decoder configurations
 */
typedef enum
{
	ADEC_PCMPNUM = 0,
	ADEC_PCMPLIST,

	ADEC_NAME,
	ADEC_USECOUNT,
	ADEC_TOKEN,
	ADEC_ANYSIZE,
	ADEC_ANY,
	ADEC_ANYATTR,

	ADEC_MAX_POS
}ADEC_CONFIG_POS;
static const int adec_config_num = 1;
static char *adec_configurations[CONFIG_NUM][8] = 
{
	{
		"0",//the number of compatible profile: 0 -- all compatible
		"*", //compatible profile list

		"adecoder_1",//name
		"0",//usecount
		"adecoder_1",//token
		"0",//any size
		NULL,//any
		NULL//__anyAttribute
	}
};

#define CLASS_PROFILE "Profiles"
#define CLASS_VECFG   "VideoEncoder Configurations"
#define CLASS_VSCFG   "VideoSource Configurations"
#define CLASS_VOCFG   "VideoOutput Configurations"
#define CLASS_ASCFG   "AudioSource Configurations"
#define CLASS_AOCFG   "AudioOutput Configurations"
#define CLASS_AECFG   "AudioEncoder Configurations"
#define CLASS_ADECFG  "AudioDecoder Configurations"
#define CLASS_VACFG   "VideoAnalytics Configurations"

#define DEFAULT_CONFIG_FILE "onvif.config"
#define LINE_LEN 512
static char line[LINE_LEN]={0};

int store_config_helper(FILE *stream, char **config,int elem_size,int token_pos)
{
	int j;

	snprintf(line,LINE_LEN,"@%s\n",*(config+token_pos));
	fwrite(line,strlen(line),1,stream);
	fwrite("{\n",2,1,stream);
	for(j=0;j<elem_size;j++)
	{
		if(*(config+j)!=NULL)
		{
			snprintf(line,LINE_LEN,"\t%s\n",*(config+j));
			fwrite(line,strlen(line),1,stream);
		}
		else
		{
			snprintf(line,LINE_LEN,"\tNULL\n");
			fwrite(line,strlen(line),1,stream);
		}
	}
	fwrite("}\n",2,1,stream);

	return 0;
}

int store_config_default(const char *name, char *configs[], int config_num, int elem_size)
{
	if(name == NULL || configs == NULL)
	{
		printf("invalid params!\n");
		return -1;
	}

	int i,j;
	int fd = -1;
	FILE *stream;

	fd = open(DEFAULT_CONFIG_FILE, O_CREAT|O_WRONLY|O_APPEND,0777);

	if(fd < 0)
	{
		printf("open %s fail.\n", DEFAULT_CONFIG_FILE);
		return -1;
	}
	stream = fdopen(fd, "w");
	snprintf(line,LINE_LEN,"## %s ##\n",name);
	fwrite(line,strlen(line),1,stream);
	snprintf(line,LINE_LEN,"@total=%d\n",config_num);
	fwrite(line,strlen(line),1,stream);

	int bytes = elem_size;
	for(i=0;i<config_num;i++)
	{
		if(strstr(name,CLASS_PROFILE)!=NULL)
		{
			store_config_helper(stream,configs+i*bytes,elem_size,PF_TOKEN);
		}
		else if(strstr(name,CLASS_VECFG)!=NULL)
		{
			store_config_helper(stream,configs+i*bytes,elem_size,VE_TOKEN);
		}
		else if(strstr(name,CLASS_VSCFG)!=NULL)
		{
			store_config_helper(stream,configs+i*bytes,elem_size,VS_TOKEN);
		}
		else if(strstr(name,CLASS_VOCFG)!=NULL)
		{
			store_config_helper(stream,configs+i*bytes,elem_size,VO_TOKEN);
		}
		else if(strstr(name,CLASS_ASCFG)!=NULL)
		{
			store_config_helper(stream,configs+i*bytes,elem_size,AS_TOKEN);
		}
		else if(strstr(name,CLASS_AOCFG)!=NULL)
		{
			store_config_helper(stream,configs+i*bytes,elem_size,AO_TOKEN);
		}
		else if(strstr(name,CLASS_AECFG)!=NULL)
		{
			store_config_helper(stream,configs+i*bytes,elem_size,AE_TOKEN);
		}
		else if(strstr(name,CLASS_ADECFG)!=NULL)
		{
			store_config_helper(stream,configs+i*bytes,elem_size,ADEC_TOKEN);
		}
	}

	fclose(stream);

	return 0;
}

int main(int argc, char *argv[])
{
	int ret;
	store_config_default(CLASS_PROFILE,profiles,profile_num,PF_MAX_POS);
	store_config_default(CLASS_VECFG,ve_configurations,ve_config_num,VE_MAX_POS);
	store_config_default(CLASS_VSCFG,vs_configurations,vs_config_num,VS_MAX_POS);
	store_config_default(CLASS_VOCFG,vo_configurations,vo_config_num,VO_MAX_POS);
	store_config_default(CLASS_ASCFG,as_configurations,as_config_num,AS_MAX_POS);
	store_config_default(CLASS_AOCFG,ao_configurations,ao_config_num,AO_MAX_POS);
	store_config_default(CLASS_AECFG,ae_configurations,ae_config_num,AE_MAX_POS);
	ret = store_config_default(CLASS_ADECFG,adec_configurations,adec_config_num,ADEC_MAX_POS);

	printf("ret = %d\n",ret);

	return 0;
}
